package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.ReqSpuDTO;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: SGS
 * @Date : 2020/11/17 16:44
 * @Version :
 */
@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Resource
    private BrandService brandService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private SkuService skuService;
    @Resource
    private SpuDetailService spuDetailService;
    @Resource
    private AmqpTemplate amqpTemplate;

    @Override
    public PageDTO<SpuDTO> querySpuByPage(ReqSpuDTO reqSpu) {
        int current = Math.max(reqSpu.getPage(), 1);
        int size = Math.max(reqSpu.getRows(), 5);
        Page<Spu> spuPage = query()
                .eq(reqSpu.getBrandId() != null, "brand_id", reqSpu.getBrandId())
                .eq(reqSpu.getCategoryId() != null, "cid3", reqSpu.getCategoryId())
                .eq(reqSpu.getSaleable() != null, "saleable", reqSpu.getSaleable())
                .eq(reqSpu.getId() != null, "id", reqSpu.getId())
                .page(new Page<>(current, size));
        List<Spu> list = spuPage.getRecords();
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(list);
        for (SpuDTO spu : spuDTOS) {
            handleCategoryAndBrandName(spu);
        }
        return new PageDTO<>(spuPage.getTotal(), spuPage.getPages(), spuDTOS);
    }

    /**
     * 添加商品
     *
     * @param spuDTO
     */
    @Override
    @Transactional
    public void saveGoods(SpuDTO spuDTO) {
        //1.保存spu
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean save = save(spu);
        if (!save) {
            throw new LyException(500, "添加Spu商品失败");
        }
        //2.保存spu下的sku集合
        List<SkuDTO> skus = spuDTO.getSkus();
        List<Sku> skuList = skus.stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
        //批量保存sku
        boolean saveSkus = skuService.saveBatch(skuList);
        if (!saveSkus) {
            throw new LyException(500, "添加sku集合失败");
        }
        //3.保存supDetail
        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        SpuDetail spuDetail1 = spuDetail.toEntity(SpuDetail.class);
        spuDetail1.setSpuId(spu.getId());
        boolean detail = spuDetailService.save(spuDetail1);
        if (!detail) {
            throw new LyException(500, "添加spuDetail失败");
        }
    }

    /**
     * 修改spu
     * @param spuDTO
     */
    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
      /*  //1.修改sou
        //判断spu的id是否存在,有就改
        if (spuDTO.getId() != null) {
            Spu spu = spuDTO.toEntity(Spu.class);
            boolean spuSuccess = updateById(spu);
            if (!spuSuccess) {
                throw new LyException(500, "更新失败");
            }
        }
        //2.更新sku
        List<SkuDTO> skus = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(skus)) {
            return;
        }
        //判断saleable是否为null,不是null删除
        Map<Boolean, List<Sku>> map = skus.stream().map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
        //获取为null的sku做修改或新增
        List<Sku> trueSku = map.get(true);
        if (!CollectionUtils.isEmpty(trueSku)) {
            skuService.saveOrUpdateBatch(trueSku);
        }
        //获取要删除的sku
        List<Sku> falseSku = map.get(false);
        if (!CollectionUtils.isEmpty(falseSku)) {
            List<Long> idList = falseSku.stream().map(Sku::getId).collect(Collectors.toList());
            skuService.removeByIds(idList);
        }
        //3.更新spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        if (spuDetailDTO != null && spuDetailDTO.getSpuId() != null) {
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            boolean updateDetail = spuDetailService.updateById(spuDetail);
            if (!updateDetail) {
                throw new LyException(500, "商品更新失败");
            }
        }*/
        // 1.修改spu
        // 1.1.判断是否存在spu的id，有说明需要修改，没有说明不需要
        Long spuId = spuDTO.getId();
        if(spuId != null){
            // 1.2.spu需要修改，更新spu, 转换dto
            Spu spu = spuDTO.toEntity(Spu.class);
            // 1.3.更新
            boolean success = updateById(spu);
            if(!success){
                // 更新失败，抛出异常
                throw new LyException(500, "更新商品失败！");
            }
        }
        // 2.修改spuDetail
        SpuDetailDTO detailDTO = spuDTO.getSpuDetail();
        // 2.1.判断是否为null
        if (detailDTO != null && detailDTO.getSpuId() != null) {
            // 2.2.spuDetail存在，需要修改，转换DTO
            SpuDetail detail = detailDTO.toEntity(SpuDetail.class);
            boolean success = spuDetailService.updateById(detail);
            if(!success){
                // 更新失败，抛出异常
                throw new LyException(500, "更新商品失败！");
            }
        }
        // 3.修改sku
        List<SkuDTO> dtoList = spuDTO.getSkus();
        // 3.1.判断是否包含sku
        if(CollectionUtils.isEmpty(dtoList)){
            return;
        }
        // 3.2.转换DTO，并将sku根据saleable是否为null来分组。null，是新增或修改，不是null是删除
        Map<Boolean, List<Sku>> map = dtoList.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));

        // 3.3.获取要新增或修改的sku
        List<Sku> insertOrUpdateList = map.get(true);
        // 如果不为空，则修改或新增
        if(!CollectionUtils.isEmpty(insertOrUpdateList)) {
            skuService.saveOrUpdateBatch(insertOrUpdateList);
        }

        // 3.4.获取要删除的sku
        List<Sku> deleteSkuList = map.get(false);
        if(!CollectionUtils.isEmpty(deleteSkuList)){
            // 存在要删除的sku
            List<Long> idList = deleteSkuList.stream().map(Sku::getId).collect(Collectors.toList());
            // 删除
            skuService.removeByIds(idList);
        }
    }

    @Override
    @Transactional
    public void updateSpuSaleable(Long id, Boolean saleable) {
        //更新spu
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean success = updateById(spu);
        if (!success){
            throw new LyException(500,"更新失败");
        }
        //更新sku
       success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!success){
            throw new LyException(500,"更新失败");
        }
        String routingKey= saleable ? MQConstants.RoutingKeyConstants.ITEM_UP_KEY:
                MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME,routingKey,id);
    }

    @Override
    public SpuDTO querySpuSkuDetailById(Long id) {
        //查询spu
        Spu spu = getById(id);
        if (spu==null){
            throw new LyException(500,"查询失败");
        }
        //转化成DTO格式
        SpuDTO dto = new SpuDTO(spu);
        //查询sku集合
        List<Sku> skus = skuService.query().eq("spu_id", id).list();
        if (skus == null){
            throw new LyException(500,"查询失败");
        }
        //转换sku格式为skuDTO
        List<SkuDTO> skuDTOS = SkuDTO.convertEntityList(skus);
        dto.setSkus(skuDTOS);
        //查询detail
        SpuDetail detail = spuDetailService.getById(id);
        if (detail == null){
            throw new LyException(500,"查询失败");
        }
        SpuDetailDTO dtoD = new SpuDetailDTO(detail);
        dto.setSpuDetail(dtoD);
        //准备商品分类和品牌名称
        handleCategoryAndBrandName(dto);
        return dto;
    }


    private void handleCategoryAndBrandName(SpuDTO spu) {
        //添加品牌名称
        Brand brand = brandService.getById(spu.getBrandId());
        if (brand != null) {
            String brandName = brand.getName();
            spu.setBrandName(brandName);
        }
        //添加分类名称
        List<Category> categories = categoryService.listByIds(spu.getCategoryIds());

        if (!CollectionUtils.isEmpty(categories)) {

            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spu.setCategoryName(names);
        }
    }
}
